package com.brightgenerous.niconama02.player;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JTextArea;
import javax.swing.WindowConstants;
import javax.swing.border.EtchedBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;

import com.brightgenerous.niconama02.stage.Moment;
import com.brightgenerous.niconama02.stage.Moment.Type;

/**
 * <p>
 * ビジュアルプレーヤー
 * </p>
 * <p>
 * {@link VisualRecoder}が録画したデータを再生できる
 * </p>
 * 
 * @author brigen
 */
public class VisualPlayer {

	/** メインのウィンドウ */
	private JFrame p_frame;

	/** 背景グラフィック */
	private BackgroundComponent p_background;

	/** 顔グラフィック */
	private FaceComponent p_face;

	/** 台詞 */
	private VoiceComponent p_voice;

	/** 次へボタン */
	JButton p_button;

	/** 録画データ */
	private List<Moment> p_moments;

	/** シーク位置 */
	private int p_index;

	/**
	 * [constructor]
	 */
	public VisualPlayer() {
		init();
	}

	/**
	 * 初期化する
	 */
	private void init() {
		p_frame = new JFrame("初心者のための逆に考えるオブジェクト指向");
		p_frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
		{
			JRootPane root = p_frame.getRootPane();
			root.setLayout(new BorderLayout());
			{
				p_background = new BackgroundComponent();
				root.add(BorderLayout.CENTER, p_background);
			}
			{
				JPanel panel = new JPanel();
				panel.setLayout(new BorderLayout());
				{
					p_face = new FaceComponent();
					panel.add(BorderLayout.WEST, p_face);
				}
				{
					p_voice = new VoiceComponent("");
					panel.add(BorderLayout.CENTER, p_voice);
				}
				{
					p_button = new JButton(">>");
					p_button.addActionListener(new ActionListener() {
						
						@Override
						public void actionPerformed(ActionEvent x_event) {
							if (hasNextMoment()) {
								nextMoment();
							} else {
								p_button.setEnabled(false);
							}
						}
					});
					panel.add(BorderLayout.EAST, p_button);
				}
				root.add(BorderLayout.SOUTH, panel);
			}
		}
	}

	/**
	 * 録画データを再生する
	 *
	 * @param x_recoder レコーダー
	 */
	public void play(VisualRecoder x_recoder) {
		p_moments = x_recoder.getMoments();
		if (!hasNextMoment()) {
			p_button.setEnabled(false);
		}
		p_frame.setBounds(500, 300, 640, 480);
		p_frame.setVisible(true);
	}

	/**
	 * <p>
	 * 次のシーンがあるかどうかを調べる
	 * </p>
	 * <p>
	 * 次のシーンがあれば真を返す
	 * </p>
	 *
	 * @return 次のシーンがあれば真、なければ偽
	 */
	boolean hasNextMoment() {
		return p_index < p_moments.size();
	}

	/**
	 * 次のシーンへ
	 *
	 * @return 
	 */
	void nextMoment() {
		Moment moment = p_moments.get(p_index++);

		Type type = moment.getType();

		StringBuilder text = new StringBuilder();

		if (type.equals(Type.BOTH) || type.equals(Type.SCENE)) {
			URL picture = moment.getPicture();
			if (picture != null) {
				p_background.setImage(new ImageIcon(picture).getImage());
			} else {
				p_background.setImage(null);
			}
			String scene = moment.getScene();
			String sound = moment.getSound();
			if ((scene != null) && !scene.equals("")) {
				text.append("-----").append(scene).append("-----");
				if ((sound != null) && !sound.equals("")) {
					text.append("< ").append(sound).append(" >");
				}
			}
		}
		if (type.equals(Type.BOTH) || type.equals(Type.FACE)) {
			String voice = moment.getVoice();
			if ((voice != null) && !voice.equals("")) {
				text.append("「").append(voice).append("」");
			}
			String name = moment.getName();
			if ((name != null) && !name.equals("")) {
				p_face.setName(name);
			} else {
				p_face.setName("");
			}
			URL face = moment.getFace();
			if (face != null) {
				p_face.setImage(new ImageIcon(face).getImage());
			} else {
				p_face.setImage(null);
			}
		}

		p_voice.setText(text.toString());

		p_frame.getRootPane().updateUI();
	}

	/**
	 * 背景グラフィックのコンポーネント
	 * 
	 * @author brigen
	 */
	static class BackgroundComponent extends JComponent {

		/** シリアルバージョンID */
		private static final long serialVersionUID = -3406325875887726379L;

		/** 背景画像 */
		private Image p_image;

		/**
		 * [constructor]
		 */
		BackgroundComponent() {
			init();
		}

		/**
		 * 初期化する
		 */
		private void init() {
			setBackground(Color.WHITE);
		}

		@Override
		public void paintComponent(Graphics x_graphics) {
			if (p_image != null) {
				x_graphics.drawImage(p_image, 0, 0, getWidth(), getHeight(), this);
			} else {
				x_graphics.setColor(Color.WHITE);
				x_graphics.fillRect(0, 0, getWidth(), getHeight());
			}
			super.paintComponent(x_graphics);
		}

		/**
		 * 背景画像を設定する
		 *
		 * @param x_image 背景画像
		 */
		public void setImage(Image x_image) {
			p_image = x_image;
		}
	}

	/**
	 * 台詞のコンポーネント
	 * 
	 * @author brigen
	 */
	static class VoiceComponent extends JTextArea {

		/** シリアルバージョンID */
		private static final long serialVersionUID = -7805500697088551730L;

		/**
		 * [constructor]
		 */
		VoiceComponent() {
			this("");
		}

		/**
		 * 
		 * [constructor]
		 *
		 * @param x_text 台詞
		 */
		VoiceComponent(String x_text) {
			super(x_text);
			init();
		}

		/**
		 * 初期化する
		 */
		private void init() {
			setLineWrap(true);
			setWrapStyleWord(true);
			setFont(new Font("Serif", Font.PLAIN, 20));
			setBorder(new EtchedBorder());
			setEditable(false);
		}
	}

	/**
	 * 顔グラフィックのコンポーネント
	 * 
	 * @author brigen
	 */
	static class FaceComponent extends JComponent {

		/** シリアルバージョンID */
		private static final long serialVersionUID = -3406325875887726379L;

		/** 名前とボーダー */
		private TitledBorder p_titleBorder;

		/** 顔画像 */
		private Image p_image;

		/**
		 * [constructor]
		 */
		FaceComponent() {
			init();
		}

		/**
		 * 初期化する
		 */
		private void init() {
			p_titleBorder = new TitledBorder(new LineBorder(Color.PINK, 3 , true), "", TitledBorder.CENTER, TitledBorder.BOTTOM, new Font("Serif", Font.BOLD, 20), Color.RED);
			setBorder(p_titleBorder);
			setBackground(Color.WHITE);
		}

		@Override
		public Dimension getPreferredSize() {
			return new Dimension(200, 200);
		}

		@Override
		public void paintComponent(Graphics x_graphics) {
			if (p_image != null) {
				x_graphics.drawImage(p_image, 0, 0, getWidth(), getHeight(), this);
			} else {
				x_graphics.setColor(Color.WHITE);
				x_graphics.fillRect(0, 0, getWidth(), getHeight());
			}
			super.paintComponent(x_graphics);
		}

		/**
		 * 顔画像を設定する
		 *
		 * @param x_image 顔画像
		 */
		public void setImage(Image x_image) {
			p_image = x_image;
		}

		/**
		 * 名前を設定する
		 * 
		 * @param x_name 名前
		 */
		@Override
		public void setName(String x_name) {
			super.setName(x_name);
			p_titleBorder.setTitle(x_name);
		}
	}
}